use std::{convert::TryInto, io::{Read, Seek, SeekFrom}};

use crate::io::IOError;

pub(crate) fn read_data<T: Read + Seek>(
    reader: &mut T,
    start: u64,
    limit: u64,
) -> Result<Vec<u8>, IOError> {
    match reader.seek(SeekFrom::Start(start)) {
        Ok(_) => {
            let mut t = reader.take(limit);
            let mut buf = Vec::new();
            match t.read_to_end(&mut buf) {
                Ok(n) if n > 0 => Ok(buf),
                Ok(_) => Err(IOError::ReadCompleted(start, limit)),
                Err(e) => Err(IOError::ReadError(e.to_string())),
            }
        }
        Err(e) => Err(IOError::ReadError(e.to_string())),
    }
}

/// 在指定位置，读取指定长度的字节数，并转换成字符串
pub(crate) fn read_string<T: Read + Seek>(
    mut reader: &mut T,
    start: u64,
    limit: u64,
) -> Result<String, IOError> {
    match read_data(&mut reader, start, limit) {
        Ok(buf) => match String::from_utf8(buf) {
            Ok(s) => Ok(s),
            Err(e) => Err(IOError::ReadError(e.to_string())),
        },
        Err(e) => Err(e),
    }
}

/// 在指定位置，读取8个字节，并转换成一个u64
pub(crate) fn read_u64<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<u64, IOError> {
    match read_data(&mut reader, start, 8) {
        Ok(buf) => Ok(u64::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}

pub(crate) fn read_i64<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<i64, IOError> {
    match read_data(&mut reader, start, 8) {
        Ok(buf) => Ok(i64::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}

pub(crate) fn read_f64<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<f64, IOError> {
    match read_data(&mut reader, start, 8) {
        Ok(buf) => Ok(f64::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}

/// 在指定位置，读取四个字节，并转换成一个u32
pub(crate) fn read_u32<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<u32, IOError> {
    match read_data(&mut reader, start, 4) {
        Ok(buf) => Ok(u32::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}

pub(crate) fn read_i32<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<i32, IOError> {
    match read_data(&mut reader, start, 4) {
        Ok(buf) => Ok(i32::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}

pub(crate) fn read_f32<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<f32, IOError> {
    match read_data(&mut reader, start, 4) {
        Ok(buf) => Ok(f32::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}

/// 在指定位置，读取两个字节，并转换成一个u16
pub fn read_u16<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<u16, IOError> {
    match read_data(&mut reader, start, 2) {
        Ok(buf) => Ok(u16::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}

pub fn read_i16<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<i16, IOError> {
    match read_data(&mut reader, start, 1) {
        Ok(buf) => Ok(i16::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}

pub fn read_u8<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<u8, IOError> {
    match read_data(&mut reader, start, 1) {
        Ok(buf) => Ok(u8::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}

pub fn read_i8<T: Read + Seek>(mut reader: &mut T, start: u64) -> Result<i8, IOError> {
    match read_data(&mut reader, start, 1) {
        Ok(buf) => Ok(i8::from_be_bytes(buf.try_into().unwrap())),
        Err(e) => Err(e),
    }
}